package net.sf.gazpachoquest.services.permission.impl; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import net.sf.gazpachoquest.domain.support.Permission; import net.sf.gazpachoquest.domain.support.Securizable; import net.sf.gazpachoquest.domain.user.Group; import net.sf.gazpachoquest.types.Perm; import org.springframework.data.jpa.domain.Specification; public class PermissionSpecification<T extends Securizable<?>, P extends Permission<T>> { private final static Integer READ_ONLY = Perm.READ.getMask(); public Specification<T> canRead(final Integer userId, final Integer... roleIds) { return new Specification<T>() { @Override public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) { query.distinct(true); Join<T, P> permission = root.join("permissions", JoinType.LEFT); Path<Integer> userIdPath = permission.get("user").get("id"); Path<Integer> maskPath = permission.get("mask"); Predicate matchUserId = cb.equal(userIdPath, userId); Expression<Integer> readPermission = cb.mod(cb.quot(maskPath, READ_ONLY).as(Integer.class), 2); Predicate canRead = cb.equal(readPermission, 1); Predicate predicate = null; if (roleIds.length > 0) { Path<Group> group = permission.get("role"); Predicate inGroups = group.in((Object[]) roleIds); predicate = cb.and(cb.or(inGroups, matchUserId), canRead); } else { predicate = cb.and(matchUserId, canRead); } return predicate; } }; } }